001    /*
002     *  Copyright 2001-2005,2008 Stephen Colebourne
003     *
004     *  Licensed under the Apache License, Version 2.0 (the "License");
005     *  you may not use this file except in compliance with the License.
006     *  You may obtain a copy of the License at
007     *
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     *
010     *  Unless required by applicable law or agreed to in writing, software
011     *  distributed under the License is distributed on an "AS IS" BASIS,
012     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     *  See the License for the specific language governing permissions and
014     *  limitations under the License.
015     */
016    package org.joda.time;
017    
018    import java.io.Serializable;
019    
020    import org.joda.time.base.BaseDuration;
021    import org.joda.time.field.FieldUtils;
022    
023    /**
024     * An immutable duration specifying a length of time in milliseconds.
025     * <p>
026     * A duration is defined by a fixed number of milliseconds.
027     * There is no concept of fields, such as days or seconds, as these fields can vary in length.
028     * A duration may be converted to a {@link Period} to obtain field values.
029     * This conversion will typically cause a loss of precision however.
030     * <p>
031     * Duration is thread-safe and immutable.
032     *
033     * @author Brian S O'Neill
034     * @author Stephen Colebourne
035     * @since 1.0
036     */
037    public final class Duration
038            extends BaseDuration
039            implements ReadableDuration, Serializable {
040    
041        /** Constant representing zero millisecond duration */
042        public static final Duration ZERO = new Duration(0L);
043    
044        /** Serialization version */
045        private static final long serialVersionUID = 2471658376918L;
046    
047        //-----------------------------------------------------------------------
048        /**
049         * Create a duration with the specified number of days assuming that
050         * there are the standard number of milliseconds in a day.
051         * <p>
052         * This method assumes that there are 24 hours in a day,
053         * 60 minutes in an hour, 60 seconds in a minute and 1000 milliseconds in
054         * a second. This will be true for most days, however days with Daylight
055         * Savings changes will not have 24 hours, so use this method with care.
056         * <p>
057         * A Duration is a representation of an amount of time. If you want to express
058         * the concepts of 'days' you should consider using the {@link Days} class.
059         *
060         * @param days  the number of standard days in this duration
061         * @return the duration, never null
062         * @throws ArithmeticException if the days value is too large
063         * @since 1.6
064         */
065        public static Duration standardDays(long days) {
066            if (days == 0) {
067                return ZERO;
068            }
069            return new Duration(FieldUtils.safeMultiply(days, DateTimeConstants.MILLIS_PER_DAY));
070        }
071    
072        /**
073         * Create a duration with the specified number of hours assuming that
074         * there are the standard number of milliseconds in an hour.
075         * <p>
076         * This method assumes that there are 60 minutes in an hour,
077         * 60 seconds in a minute and 1000 milliseconds in a second.
078         * All currently supplied chronologies use this definition.
079         * <p>
080         * A Duration is a representation of an amount of time. If you want to express
081         * the concepts of 'hours' you should consider using the {@link Hours} class.
082         *
083         * @param hours  the number of standard hours in this duration
084         * @return the duration, never null
085         * @throws ArithmeticException if the hours value is too large
086         * @since 1.6
087         */
088        public static Duration standardHours(long hours) {
089            if (hours == 0) {
090                return ZERO;
091            }
092            return new Duration(FieldUtils.safeMultiply(hours, DateTimeConstants.MILLIS_PER_HOUR));
093        }
094    
095        /**
096         * Create a duration with the specified number of minutes assuming that
097         * there are the standard number of milliseconds in a minute.
098         * <p>
099         * This method assumes that there are 60 seconds in a minute and
100         * 1000 milliseconds in a second.
101         * All currently supplied chronologies use this definition.
102         * <p>
103         * A Duration is a representation of an amount of time. If you want to express
104         * the concepts of 'minutes' you should consider using the {@link Minutes} class.
105         *
106         * @param minutes  the number of standard minutes in this duration
107         * @return the duration, never null
108         * @throws ArithmeticException if the minutes value is too large
109         * @since 1.6
110         */
111        public static Duration standardMinutes(long minutes) {
112            if (minutes == 0) {
113                return ZERO;
114            }
115            return new Duration(FieldUtils.safeMultiply(minutes, DateTimeConstants.MILLIS_PER_MINUTE));
116        }
117    
118        /**
119         * Create a duration with the specified number of seconds assuming that
120         * there are the standard number of milliseconds in a second.
121         * <p>
122         * This method assumes that there are 1000 milliseconds in a second.
123         * All currently supplied chronologies use this definition.
124         * <p>
125         * A Duration is a representation of an amount of time. If you want to express
126         * the concepts of 'seconds' you should consider using the {@link Seconds} class.
127         *
128         * @param seconds  the number of standard seconds in this duration
129         * @return the duration, never null
130         * @throws ArithmeticException if the seconds value is too large
131         * @since 1.6
132         */
133        public static Duration standardSeconds(long seconds) {
134            if (seconds == 0) {
135                return ZERO;
136            }
137            return new Duration(FieldUtils.safeMultiply(seconds, DateTimeConstants.MILLIS_PER_SECOND));
138        }
139    
140        //-----------------------------------------------------------------------
141        /**
142         * Creates a duration from the given millisecond duration.
143         *
144         * @param duration  the duration, in milliseconds
145         */
146        public Duration(long duration) {
147            super(duration);
148        }
149    
150        /**
151         * Creates a duration from the given interval endpoints.
152         *
153         * @param startInstant  interval start, in milliseconds
154         * @param endInstant  interval end, in milliseconds
155         * @throws ArithmeticException if the duration exceeds a 64 bit long
156         */
157        public Duration(long startInstant, long endInstant) {
158            super(startInstant, endInstant);
159        }
160    
161        /**
162         * Creates a duration from the given interval endpoints.
163         *
164         * @param start  interval start, null means now
165         * @param end  interval end, null means now
166         * @throws ArithmeticException if the duration exceeds a 64 bit long
167         */
168        public Duration(ReadableInstant start, ReadableInstant end) {
169            super(start, end);
170        }
171    
172        /**
173         * Creates a duration from the specified object using the
174         * {@link org.joda.time.convert.ConverterManager ConverterManager}.
175         *
176         * @param duration  duration to convert
177         * @throws IllegalArgumentException if duration is invalid
178         */
179        public Duration(Object duration) {
180            super(duration);
181        }
182    
183        //-----------------------------------------------------------------------
184        /**
185         * Gets the length of this duration in seconds assuming 1000 milliseconds
186         * in a second.
187         * <p>
188         * This returns <code>getMillis() / 1000</code>.
189         * The result is an integer division, so 2999 millis returns 2 seconds.
190         *
191         * @return the length of the duration in standard seconds
192         * @since 1.6
193         */
194        public long getStandardSeconds() {
195            return getMillis() / DateTimeConstants.MILLIS_PER_SECOND;
196        }
197    
198        //-----------------------------------------------------------------------
199        /**
200         * Get this duration as an immutable <code>Duration</code> object
201         * by returning <code>this</code>.
202         * 
203         * @return <code>this</code>
204         */
205        public Duration toDuration() {
206            return this;
207        }
208    
209        /**
210         * Converts this duration to a period in seconds assuming 1000 milliseconds
211         * in a second.
212         * <p>
213         * This method allows you to convert between a duration and a period.
214         * 
215         * @return a period representing the number of standard seconds in this period, never null
216         * @throws ArithmeticException if the number of seconds is too large to be represented
217         * @since 1.6
218         */
219        public Seconds toStandardSeconds() {
220            long seconds = getStandardSeconds();
221            return Seconds.seconds(FieldUtils.safeToInt(seconds));
222        }
223    
224        //-----------------------------------------------------------------------
225        /**
226         * Creates a new Duration instance with a different milisecond length.
227         * 
228         * @param duration  the new length of the duration
229         * @return the new duration instance
230         */
231        public Duration withMillis(long duration) {
232            if (duration == getMillis()) {
233                return this;
234            }
235            return new Duration(duration);
236        }
237    
238        /**
239         * Returns a new duration with this length plus that specified multiplied by the scalar.
240         * This instance is immutable and is not altered.
241         * <p>
242         * If the addition is zero, this instance is returned.
243         * 
244         * @param durationToAdd  the duration to add to this one
245         * @param scalar  the amount of times to add, such as -1 to subtract once
246         * @return the new duration instance
247         */
248        public Duration withDurationAdded(long durationToAdd, int scalar) {
249            if (durationToAdd == 0 || scalar == 0) {
250                return this;
251            }
252            long add = FieldUtils.safeMultiply(durationToAdd, scalar);
253            long duration = FieldUtils.safeAdd(getMillis(), add);
254            return new Duration(duration);
255        }
256    
257        /**
258         * Returns a new duration with this length plus that specified multiplied by the scalar.
259         * This instance is immutable and is not altered.
260         * <p>
261         * If the addition is zero, this instance is returned.
262         * 
263         * @param durationToAdd  the duration to add to this one, null means zero
264         * @param scalar  the amount of times to add, such as -1 to subtract once
265         * @return the new duration instance
266         */
267        public Duration withDurationAdded(ReadableDuration durationToAdd, int scalar) {
268            if (durationToAdd == null || scalar == 0) {
269                return this;
270            }
271            return withDurationAdded(durationToAdd.getMillis(), scalar);
272        }
273    
274        //-----------------------------------------------------------------------
275        /**
276         * Returns a new duration with this length plus that specified.
277         * This instance is immutable and is not altered.
278         * <p>
279         * If the addition is zero, this instance is returned.
280         * 
281         * @param amount  the duration to add to this one
282         * @return the new duration instance
283         */
284        public Duration plus(long amount) {
285            return withDurationAdded(amount, 1);
286        }
287    
288        /**
289         * Returns a new duration with this length plus that specified.
290         * This instance is immutable and is not altered.
291         * <p>
292         * If the amount is zero, this instance is returned.
293         * 
294         * @param amount  the duration to add to this one, null means zero
295         * @return the new duration instance
296         */
297        public Duration plus(ReadableDuration amount) {
298            if (amount == null) {
299                return this;
300            }
301            return withDurationAdded(amount.getMillis(), 1);
302        }
303    
304        /**
305         * Returns a new duration with this length minus that specified.
306         * This instance is immutable and is not altered.
307         * <p>
308         * If the addition is zero, this instance is returned.
309         * 
310         * @param amount  the duration to take away from this one
311         * @return the new duration instance
312         */
313        public Duration minus(long amount) {
314            return withDurationAdded(amount, -1);
315        }
316    
317        /**
318         * Returns a new duration with this length minus that specified.
319         * This instance is immutable and is not altered.
320         * <p>
321         * If the amount is zero, this instance is returned.
322         * 
323         * @param amount  the duration to take away from this one, null means zero
324         * @return the new duration instance
325         */
326        public Duration minus(ReadableDuration amount) {
327            if (amount == null) {
328                return this;
329            }
330            return withDurationAdded(amount.getMillis(), -1);
331        }
332    
333    }